package util;

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.function.Consumer;

public class ListaOrdinataConcatenata<T extends Comparable<? super T>> extends
		CollezioneAstratta<T> {

	private class MioIteratore implements Iterator<T> {// inner class.

		private Nodo<T> pre = null, cor = null;

		@Override
		public boolean hasNext() {
			if (cor == null)
				return testa != null;

			return cor.next != null;
		}

		@Override
		public T next() {
			if (!hasNext())
				throw new NoSuchElementException();

			if (cor == null)
				cor = testa;
			else {
				pre = cor;
				cor = cor.next;

			}
			return cor.info;

		}// next

		@Override
		public void remove() {
			if (pre == cor)
				throw new IllegalStateException();
			if (cor == testa)
				testa = cor.next;
			else
				pre.next = cor.next;
			cor = pre;// arretra cor.
			size--;
		}// remove

		@Override
		public void forEachRemaining(Consumer<? super T> arg0) {
			// TODO Auto-generated method stub

		}

	}

	private static class Nodo<E> {
		E info;
		Nodo<E> next;
	}

	private Nodo<T> testa = null;
	private int size = 0;

	@Override
	public int size() {
		return size;
	}

	@Override
	public T get(T x) {
		Nodo<T> cor = testa;
		while (cor != null) {
			if (cor.equals(x))
				return cor.info;
			if (cor.info.compareTo(x) > 0)
				return null;
			cor = cor.next;

		}
		return null;

	}// get

	@Override
	public void crea() {
		// TODO Auto-generated method stub

	}

	@Override
	public void add(T x) {
		if (testa == null || testa.info.compareTo(x) >= 0) {
			Nodo<T> nw = new Nodo<>();
			nw.info = x;
			nw.next = testa;
			testa = nw;

		} else {
			Nodo<T> pre = testa, cor = testa.next;

			while (cor != null && cor.info.compareTo(x) < 0) {
				pre = cor;
				cor = cor.next;

			}// avanza
			Nodo<T> nw = new Nodo<>();
			nw.info = x;
			nw.next = cor;
			pre.next = nw;

		}// else
		size++;

	}// add

	public void remove(T x) {// tre casi possibili il primo lista vuota, o
								// elemento insesistente caso piu
								// semplice, secondo caso, va rimossa la
								// testa(caso critiico perche potrebbe morire l'
								// interae lista.),nell' ultimo caso va rimosso
								// un elemento dallla lista, aggiornando il next
								// dell predecessore del numero che vogliamo
								// eliminare.
		Nodo<T> pre = null, cor = testa;
		while (cor != null && cor.info.compareTo(x) < 0) {
			pre = cor;
			cor = cor.next;
		}// scorrimento lista.
		if (cor != null && cor.info.equals(x)) {
			if (cor == testa)
				testa = cor.next;
			else
				pre.next = cor.next;
			size--;

		}// if esterno.

	}// remove

	public void removeAlternativo(T x) {// incompleto, NON USARE.
		if (testa == null)
			return;
		if (testa.info.equals(x)) {
			testa = testa.next;
			return;
		}
		Nodo<T> pre = testa, cor = testa.next;
		// il ciclo va fatto come quello si sopra, inoltre vanno messi i size--
		// ad ogni possibile uscita.

	}

	@Override
	public Iterator<T> iterator() {

		return new MioIteratore();
	}

	@Override
	public void forEach(Consumer<? super T> arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public Spliterator<T> spliterator() {
		// TODO Auto-generated method stub
		return null;
	}

}
